package com.dx.financehy.modules.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.dx.financehy.base.impl.CommonServiceImpl;
import com.dx.financehy.exception.BadRequestException;
import com.dx.financehy.exception.EntityExistException;
import com.dx.financehy.modules.business.domain.Business;
import com.dx.financehy.modules.business.domain.BusinessTwo;
import com.dx.financehy.modules.business.domain.dto.*;
import com.dx.financehy.modules.business.mapper.BusinessMapper;
import com.dx.financehy.modules.business.mapper.BusinessTwoMapper;
import com.dx.financehy.modules.platformClassOne.domain.PlatformClassOne;
import com.dx.financehy.modules.platformClassOne.domain.dto.AddPlatformClassDTO;
import com.dx.financehy.modules.platformClassOne.domain.dto.DelPlatformClassDTO;
import com.dx.financehy.modules.platformClassOne.domain.dto.EditPlatformClassDTO;
import com.dx.financehy.modules.platformClassOne.domain.dto.GetPlatformClassDTO;
import com.dx.financehy.modules.platformClassOne.mapper.PlatformClassOneMapper;
import com.dx.financehy.modules.platformClassTwo.domain.PlatformClassTwo;
import com.dx.financehy.modules.platformClassTwo.domain.dto.AddPlatformClassTwoDTO;
import com.dx.financehy.modules.platformClassTwo.domain.dto.EditPlatformClassTwoDTO;
import com.dx.financehy.modules.platformClassTwo.domain.dto.GetPlatformClassTwoDTO;
import com.dx.financehy.modules.platformClassTwo.mapper.PlatformClassTwoMapper;
import com.dx.financehy.modules.security.config.bean.LoginProperties;
import com.dx.financehy.modules.security.config.bean.SecurityProperties;
import com.dx.financehy.modules.security.domain.dto.OnlineUserDto;
import com.dx.financehy.modules.share.domain.UserShare;
import com.dx.financehy.modules.share.mapper.UserShareMapper;
import com.dx.financehy.modules.system.domain.User;
import com.dx.financehy.modules.system.domain.dto.*;
import com.dx.financehy.modules.system.domain.vo.*;
import com.dx.financehy.modules.system.mapper.UserMapper;
import com.dx.financehy.modules.system.service.UserService;
import com.dx.financehy.utils.BeanCopyUtil;
import com.dx.financehy.utils.ConvertUtil;
import com.dx.financehy.utils.RedisUtils;
import com.dx.financehy.utils.StringUtils;
import com.dx.financehy.utils.security.SecurityUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author: huang_jigao
 * @Title: UserServiceImpl
 * @ProjectName: financehy
 * @Description:
 * @date: 2023-12-05 15:27
 */
@Service
@AllArgsConstructor
@CacheConfig(cacheNames = "user")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
@Slf4j
public class UserServiceImpl extends CommonServiceImpl<UserMapper, User> implements UserService {

    private final PasswordEncoder passwordEncoder;
    private final UserMapper userMapper;
    private RedisUtils redisUtils;
    private final SecurityProperties properties;
    private final BusinessMapper businessMapper;
    private final BusinessTwoMapper businessTwoMapper;
    private final PlatformClassOneMapper classOneMapper;
    private final PlatformClassTwoMapper classTwoMapper;

    private final UserShareMapper userShareMapper;
    /**
     * 新增用户
     *
     * @param req
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addSysUser(AddUserDTO req){
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUsername, req.getUsername());
        wrapper.eq(User::getDeleted, false);
        User user = baseMapper.selectOne(wrapper);

        int i = 0;
        if (user != null && user.getUserType() != 3) {
            throw new BadRequestException("已存在该用户！");
        }

        if (user != null && user.getUserType() == 3) {
            user.setUserType(2);
            user.setPassword(passwordEncoder.encode(req.getPassword()));

            i = baseMapper.updateById(user);
        } else {
            user = ConvertUtil.convert(req, User.class);
            user.setPassword(passwordEncoder.encode(req.getPassword()));
            if (user == null){
                user.setUsername(req.getUsername());
            }else {
                user.setUsername(user.getUsername());
            }
            user.setEnabled(true);
            user.setIsLogin(true);

            i = baseMapper.insert(user);
        }
        if (i == 0) {
            throw new BadRequestException("新增用户失败！");
        }
    }

    /**
     * 新增用户
     *
     * @param req
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public User addLoginSysUser(AddUserDTO req){
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUsername, req.getUsername());
        wrapper.eq(User::getDeleted,false);
        User user = baseMapper.selectOne(wrapper);

        if (user != null) {
            throw new BadRequestException("已存在该用户！");
        }

        user = ConvertUtil.convert(req, User.class);
        user.setPassword(passwordEncoder.encode(req.getPassword()));
        user.setUsername(user.getUsername());
        user.setEnabled(true);
        user.setIsLogin(true);
        if (StringUtils.isNotBlank(req.getMerchantId())) {
            user.setMerchantId(req.getMerchantId());
        }
        int i = baseMapper.insert(user);
        if (i == 0) {
            throw new BadRequestException("新增用户失败！");
        }

        return user;
    }

    /**
     * 删除个人资料
     *
     * @param req
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delSysUser(BaseDTO req){
        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(User::getDeleted,true);
        updateWrapper.eq(User::getId,req.getId());
        baseMapper.update(null,updateWrapper);
    }

    /**
     * 个人资料
     *
     * @param resources
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateById(UserDto resources){
        String userId = SecurityUtils.getCurrentUserId();
        User user = getById(resources.getId());
        if (StringUtils.isNoneBlank(user.getUsername()) && user.getUsername().equals(resources.getUsername())) {
            throw new EntityExistException("不支持修改手机号,请联系管理员");
        }
        BeanUtils.copyProperties(resources,user);
        user.setUpdateBy(userId);
        userMapper.updateById(user);
    }

    @Override
    public User getByUsername(String userName) {
        User user = lambdaQuery().eq(User::getUsername, userName).one();
        return user;
    }

    /**
     * 根据wxOpenId获取用户信息
     *
     * @param wxOpenId
     * @return
     */
    @Override
    public User getByOpenId(String wxOpenId){
        User user = lambdaQuery().eq(User::getWxOpenId, wxOpenId).one();
        return user;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePass(String username, String encryptPassword, String token) {
        User user = new User();
        user.setPassword(encryptPassword);
        lambdaUpdate().eq(User::getUsername, username).update(user);

        String key = properties.getOnlineKey() + token;
        OnlineUserDto onlineUserDto = (OnlineUserDto) redisUtils.get(key);
        redisUtils.del(key);
        if (onlineUserDto != null){
            redisUtils.hdel(LoginProperties.cacheKey, onlineUserDto.getUserName());
        }
    }

    /**
     * 获取商家列表
     *
     * @param dto
     * @return
     */
    @Override
    public List<GetBusinessListVO> getBusinessList(GetBusinessListDTO dto) {
        List<GetBusinessListVO> list = new ArrayList<>();
        Integer userType = SecurityUtils.getCurrentUserType();
        if (userType != null && userType == 2){
            return list;
        }
        list = userMapper.getBusinessList(dto);
        if (CollectionUtil.isNotEmpty(list)) {
            List<String> userIds = list.stream().map(m -> m.getId()).collect(Collectors.toList());
            List<MainBusinessVO> mainBusinessVOS = businessMapper.getBusinessList(userIds);

            list.stream().forEach(o -> {
                o.setMainBusinessVOS(mainBusinessVOS.stream().filter(f -> f.getUserId().equals(o.getId())).collect(Collectors.toList()));
            });
        }
        return list;
    }



    /**
     * 获取游客列表
     *
     * @param dto
     * @return
     */
    @Override
    public List<GetBusinessListVO> getTouristList(GetBusinessListDTO dto) {
        List<GetBusinessListVO> list = new ArrayList<>();
        Integer userType = SecurityUtils.getCurrentUserType();
        String merchantId = "";
        if (userType != null && userType == 2){
            merchantId = SecurityUtils.getCurrentMerchantId();
        }
        list = userMapper.getTouristList(dto,merchantId);
        if (CollectionUtil.isNotEmpty(list)) {
            List<String> userIds = list.stream().map(m -> m.getId()).collect(Collectors.toList());
            List<MainBusinessVO> mainBusinessVOS = businessMapper.getBusinessList(userIds);

            list.stream().forEach(o -> {
                o.setMainBusinessVOS(mainBusinessVOS.stream().filter(f -> f.getUserId().equals(o.getId())).collect(Collectors.toList()));
            });
        }
        return list;
    }

    /**
     * 获取平台资源列表
     *
     * @param dto
     * @return
     */
    @Override
    public List<PlatformClassOne> getPlatformClassList(GetPlatformClassDTO dto) {
        return classOneMapper.getPlatformClassList(dto);
    }

    /**
     * 获取待审核平台资源和主营业务表
     *
     * @param dto
     * @return
     */
    @Override
    public List<IsProcessListVO> getIsProcessList(IsProcessListDTO dto){
        List<IsProcessListVO> outList = new ArrayList<>();

        List<IsProcessListVO> list = classOneMapper.getIsProcessList(dto);

        List<IsProcessListVO> twoProcessListList = classTwoMapper.getTwoProcessListList(dto);

        outList.addAll(list);
        outList.addAll(twoProcessListList);

        return outList;
    }

    /**
     * 审核平台资源和主营业务
     *
     * @param dto
     */
    @Override
    public void processPlatOrBusiness(ProcessPlatOrBusinessDTO dto){
        String userId = SecurityUtils.getCurrentUserId();
        Date date = new Date();
        if (dto.getClassOneOrtwo() == 1) {
            //1：平台资源
            if (dto.getType() == 1) {
                LambdaUpdateWrapper<PlatformClassOne> oneUpdete = new LambdaUpdateWrapper<>();
                oneUpdete.set(PlatformClassOne::getIsProcess, dto.getIsProcess())
                        .set(PlatformClassOne::getUpdateBy, userId)
                        .set(PlatformClassOne::getUpdateTime, date)
                        .eq(PlatformClassOne::getId, dto.getId());
                classOneMapper.update(null, oneUpdete);
            } else if (dto.getType() == 2) {
                //2:主营业务
                LambdaUpdateWrapper<Business> businessUpdete = new LambdaUpdateWrapper<>();
                businessUpdete.set(Business::getIsProcess, dto.getIsProcess())
                        .set(Business::getUpdateBy, userId)
                        .set(Business::getUpdateTime, date)
                        .eq(Business::getId, dto.getId());
                businessMapper.update(null, businessUpdete);
            }
        }else if (dto.getClassOneOrtwo() == 2){
            //1：平台资源
            if (dto.getType() == 1) {
                LambdaUpdateWrapper<PlatformClassTwo> twoUpdete = new LambdaUpdateWrapper<>();
                twoUpdete.set(PlatformClassTwo::getIsProcess, dto.getIsProcess())
                        .set(PlatformClassTwo::getUpdateBy, userId)
                        .set(PlatformClassTwo::getUpdateTime, date)
                        .eq(PlatformClassTwo::getId, dto.getId());
                classTwoMapper.update(null, twoUpdete);
            } else if (dto.getType() == 2) {
                //2:主营业务
                LambdaUpdateWrapper<BusinessTwo> businessTwoUpdete = new LambdaUpdateWrapper<>();
                businessTwoUpdete.set(BusinessTwo::getIsProcess, dto.getIsProcess())
                        .set(BusinessTwo::getUpdateBy, userId)
                        .set(BusinessTwo::getUpdateTime, date)
                        .eq(BusinessTwo::getId, dto.getId());
                businessTwoMapper.update(null, businessTwoUpdete);
            }
        }
    }

    /**
     * 获取总平台资源列表
     *
     * @param dto
     * @return
     */
    @Override
    public List<PlatformClassOne> getAllPlatformClassList(GetPlatformClassDTO dto) {
        List<PlatformClassOne> ones = classOneMapper.getPlatformClassList(dto);
        if (CollectionUtil.isNotEmpty(ones)){
            List<String> ids = ones.stream().map(m->m.getId()).collect(Collectors.toList());
            LambdaQueryWrapper<PlatformClassTwo> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(PlatformClassTwo::getClassOneId,ids);
            wrapper.eq(PlatformClassTwo::getDeleted,false);
            List<PlatformClassTwo> twos = classTwoMapper.selectList(wrapper);
            if (CollectionUtil.isNotEmpty(twos)){
                ones.stream().forEach(u->{
                    u.setPlatformClassTwos(twos.stream().filter(f->f.getClassOneId().equals(u.getId())).collect(Collectors.toList()));
                });
            }
        }
        return ones;
    }

    /**
     * 获取平台资源二级列表
     *
     * @param dto
     * @return
     */
    @Override
    public List<PlatformClassTwo> getPlatformClassTwoList(GetPlatformClassTwoDTO dto) {
        return classTwoMapper.getPlatformClassTwoList(dto);
    }

    /**
     * 新增平台资源
     *
     * @param dto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addPlatformClass(AddPlatformClassDTO dto) {
        String userId = SecurityUtils.getCurrentUserId();
        Date createTime = new Date();

        if (CollectionUtil.isNotEmpty(dto.getOneDTOS())) {
            dto.getOneDTOS().forEach(u -> {
                String uuId = IdUtil.simpleUUID();
                u.setId(uuId);
                if (CollectionUtil.isNotEmpty(u.getTwoDTOS())) {
                    u.getTwoDTOS().stream().forEach(o -> {
                        o.setClassOneId(uuId);
                    });
                }
            });

            classOneMapper.addPlatformClass(dto.getOneDTOS(), userId, createTime);

            dto.getOneDTOS().forEach(u -> {
                if (CollectionUtil.isNotEmpty(u.getTwoDTOS())) {
                    classTwoMapper.addPlatformClass(u.getTwoDTOS(), userId, createTime);
                }
            });

        }
    }

    /**
     * 编辑平台资源
     *
     * @param dto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void editPlatformClass(EditPlatformClassDTO dto){
        String userId = SecurityUtils.getCurrentUserId();
        Date updateTime = new Date();

        if (StringUtils.isNoneBlank(dto.getName())) {
            LambdaUpdateWrapper<PlatformClassOne> oneUpdete = new LambdaUpdateWrapper<>();
            oneUpdete.set(PlatformClassOne::getName,dto.getName())
                    .set(PlatformClassOne::getUpdateBy,userId)
                    .set(PlatformClassOne::getUpdateTime,updateTime)
                    .eq(PlatformClassOne::getDeleted,false)
                    .eq(PlatformClassOne::getId,dto.getId());
            classOneMapper.update(null,oneUpdete);

            if (CollectionUtil.isNotEmpty(dto.getTwoDTOS())){

                List<EditPlatformClassTwoDTO> addTwoDTOS = dto.getTwoDTOS().stream().filter(f->StringUtils.isBlank(f.getId())).collect(Collectors.toList());;
                List<EditPlatformClassTwoDTO> updateTwoDTOS = dto.getTwoDTOS().stream().filter(f->StringUtils.isNotBlank(f.getId())).collect(Collectors.toList());

                if (CollectionUtil.isNotEmpty(addTwoDTOS) && addTwoDTOS.size() > 0){
                    List<AddPlatformClassTwoDTO> twoDTOS = BeanCopyUtil.copyListToList(addTwoDTOS,AddPlatformClassTwoDTO.class);
                    twoDTOS.stream().forEach(u->{u.setClassOneId(dto.getId());});
                    classTwoMapper.addPlatformClass(twoDTOS, userId, updateTime);
                }

                if (CollectionUtil.isNotEmpty(updateTwoDTOS) && updateTwoDTOS.size() > 0){
                    classTwoMapper.editPlatformClass(updateTwoDTOS,userId,updateTime);
                }
            }


        }
    }

    /**
     * 删除平台资源
     *
     * @param dto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delPlatformClass(DelPlatformClassDTO dto){
        String userId = SecurityUtils.getCurrentUserId();
        Date updateTime = new Date();

        LambdaUpdateWrapper<PlatformClassOne> oneUpdate = new LambdaUpdateWrapper<>();
        oneUpdate.set(PlatformClassOne::getDeleted,true)
                .set(PlatformClassOne::getUpdateBy,userId)
                .set(PlatformClassOne::getUpdateTime,updateTime)
                .eq(PlatformClassOne::getId,dto.getId());

        classOneMapper.update(null,oneUpdate);

        LambdaUpdateWrapper<PlatformClassTwo> twoUpdate = new LambdaUpdateWrapper<>();
        twoUpdate.set(PlatformClassTwo::getDeleted,true)
                .set(PlatformClassTwo::getUpdateBy,userId)
                .set(PlatformClassTwo::getUpdateTime,updateTime)
                .eq(PlatformClassTwo::getClassOneId,dto.getId());

        classTwoMapper.update(null,twoUpdate);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateUser(UpdateUserInfoDTO dto){
        User entity = new User();
        BeanUtils.copyProperties(dto, entity);
        String currentUserId = SecurityUtils.getCurrentUserId();
        entity.setId(currentUserId);
        return updateById(entity);
    }

    /**
     * 编辑主营业务-获取主营业务
     *
     * @return
     */
    @Override
    public List<BusinessVO> getEditBusinessList(){
        String currentUserId = SecurityUtils.getCurrentUserId();
        List<BusinessVO> list = businessMapper.getEditBusinessList(currentUserId);

        if (CollectionUtil.isNotEmpty(list)){
            List<String> businessIds = list.stream().map(m->m.getBusinessId()).collect(Collectors.toList());
            List<BusinessTwoVO> twoVOS = businessTwoMapper.getEditBusinessList(businessIds);

            if (CollectionUtil.isNotEmpty(twoVOS)){
                list.stream().forEach(u->{
                    u.setTwoVOS(twoVOS.stream().filter(f->f.getClassOneId().equals(u.getBusinessId())).collect(Collectors.toList()));
                });
            }
        }
        return list;
    }

    /**
     * 编辑主营业务-新增获取主营业务
     *
     * @param dto
     */
    @Override
    public void addBusiness(AddBusinessDTO dto) {
        String userId = SecurityUtils.getCurrentUserId();
        Date createTime = new Date();

        if (CollectionUtil.isNotEmpty(dto.getBusinessOneInternals())){
            List<Business> businesses = BeanCopyUtil.copyListToList(dto.getBusinessOneInternals(),Business.class);
            if (CollectionUtil.isNotEmpty(businesses)) {
                businesses.stream().forEach(u -> {
                    u.setIsProcess(false);
                    u.setCreateBy(userId);
                    u.setCreateTime(createTime);
                });
                businessMapper.insertBatchSomeColumn(businesses);
            }
        }
    }

    /**
     * 编辑主营业务-新增获取二级主营业务
     *
     * @param dto
     */
    @Override
    public void addBusinessTwo(AddBusinessTwoDTO dto){
        String userId = SecurityUtils.getCurrentUserId();
        Date createTime = new Date();

        if (CollectionUtil.isNotEmpty(dto.getBusinessTwoInternals())){
            List<BusinessTwo> businessTwos = BeanCopyUtil.copyListToList(dto.getBusinessTwoInternals(),BusinessTwo.class);
            if (CollectionUtil.isNotEmpty(businessTwos)) {
                businessTwos.stream().forEach(u -> {
                    u.setIsProcess(false);
                    u.setCreateBy(userId);
                    u.setCreateTime(createTime);
                });
                businessTwoMapper.insertBatchSomeColumn(businessTwos);
            }
        }
    }

    /**
     * 编辑一级主营业务
     *
     * @param dto
     */
    @Override
    public void editBusiness(EditBusinessDTO dto){
        String userId = SecurityUtils.getCurrentUserId();
        Date updateTime = new Date();

        if (CollectionUtil.isNotEmpty(dto.getEditBusinessInternals())) {
            businessMapper.editBusiness(dto.getEditBusinessInternals(), userId, updateTime);
        }
    }

    /**
     * 编辑二级主营业务
     *
     * @param dto
     */
    @Override
    public void editBusinessTwo(EditBusinessTwoDTO dto){
        String userId = SecurityUtils.getCurrentUserId();
        Date updateTime = new Date();

        if (CollectionUtil.isNotEmpty(dto.getEditBusinessTwoInternals())) {
            businessTwoMapper.editBusiness(dto.getEditBusinessTwoInternals(), userId, updateTime);
        }
    }

    /**
     * 删除主营业务
     *
     * @param dto
     */
    @Override
    public void delBusiness(DelBusinessDTO dto) {
        String userId = SecurityUtils.getCurrentUserId();
        Date updateTime = new Date();

        if (CollectionUtil.isNotEmpty(dto.getIds())) {
            LambdaUpdateWrapper<Business> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.set(Business::getDeleted,true)
                    .set(Business::getUpdateTime,updateTime)
                    .set(Business::getUpdateBy,userId)
                    .in(Business::getId,dto.getIds());
            businessMapper.update(null,updateWrapper);

            LambdaUpdateWrapper<BusinessTwo> updateTwoWrapper = new LambdaUpdateWrapper<>();
            updateTwoWrapper.set(BusinessTwo::getDeleted,true)
                    .set(BusinessTwo::getUpdateTime,updateTime)
                    .set(BusinessTwo::getUpdateBy,userId)
                    .in(BusinessTwo::getClassOneId,dto.getIds());
            businessTwoMapper.update(null,updateTwoWrapper);
        }
    }

    /**
     * 删除二级主营业务
     *
     * @param dto
     */
    @Override
    public void delBusinessTwo(DelBusinessTwoDTO dto) {
        String userId = SecurityUtils.getCurrentUserId();
        Date updateTime = new Date();

        if (CollectionUtil.isNotEmpty(dto.getIds())) {
            LambdaUpdateWrapper<BusinessTwo> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.set(BusinessTwo::getDeleted,true)
                    .set(BusinessTwo::getUpdateTime,updateTime)
                    .set(BusinessTwo::getUpdateBy,userId)
                    .in(BusinessTwo::getId,dto.getIds());
            businessTwoMapper.update(null,updateWrapper);
        }
    }

    @Override
    public UserShare addShare(UserShare req){
        String userId = SecurityUtils.getCurrentUserId();
        Date createTime = new Date();

        req.setCreateBy(userId);
        req.setCreateTime(createTime);

        userShareMapper.insert(req);

        return req;
    }

    @Override
    public UserShare getShareDetail(UserShare req){
        return userShareMapper.selectById(req);
    }

    @Override
    public Integer getMaxVisitorIndex(){
        return userMapper.getMaxVisitorIndex();
    }
}
